<template>
	<view class="fusion-chat" ref="uv-back-top">
		<!-- <headers :state="state" @custom-event="e=>state = e"></headers> -->
		<el-container
			:style="$uv.os() == 'windows'?'height: calc(100vh - 50px);':'height: calc(100vh - 115px);overflow: auto;'">
			<el-container style="height:  100%;max-width: 750px;">
				<el-header style="height: 90px;padding: 0px 5px;">
					<view style="display: flex;justify-content: space-between;padding:5px 0px;">
						<uv-tabs style="width: auto;height: 40px;" :list="lists" @click="tabsclicke"></uv-tabs>
						<view class="cursor-pointer"
							style="padding:0px 10px;border: 1px solid #eee;border-radius: 5px;background-color: #f2f2f2;display: flex;justify-content: space-between;align-items: center;">
							<view @click="delex()"
								style="display: flex;justify-content: flex-start;align-items: center;">
								<i class="el-icon-delete" style="margin-top: 3px;"></i>
								<view v-if="$uv.os() == 'windows'" style="transition: width 2s;margin-left: 3px;">
									清空记录</view>
							</view>
						</view>
					</view>
					<view style="display: flex;justify-content: space-between;">
						<view class="cursor-pointer" @click="parmShow = !parmShow"
							style="border-radius: 5px;border: 1px solid #eee;padding: 5px 10px;display: flex;justify-content: flex-start;background-color: #f3f3f3;">
							{{chat.text}}<uv-icon style="margin-left: 5px;" :name="parmShow?'lock-open':'lock'"
								size="20"></uv-icon>
						</view>
					</view>
				</el-header>
				<el-main
					:style="$uv.os() == 'windows'?'width: 100%;display: flex;justify-content: center;flex-wrap: nowrap;padding: 5px;':'padding: 5px;height: calc(100vh - 205px);'">
					<view style="max-width: 750px;">
						<view :class="(parmShow && $uv.os() == 'windows')?'gpts2 gptstrue':'gpts2 gptsfalse'" style="">
							<gpts v-if="lists" :chatlist="lists[aicurrent]"
								@submit="$uv.os() != 'windows'?parmShow = false:''" :asideW="asiW"
								@custom-event="reschat">
							</gpts>
						</view>
						<view v-if="list&&list[0]" style="overflow: auto;padding: 5px;">
							<view v-for="(item,index) in list" :key="index">
								<uv-text v-if="item.createdAt&&cTime(item.createdAt,list,index)"
									:customStyle="'margin-bottom: 5px;border-radius:5px;padding:2px 5px;background-color:'+dialogueColor"
									:text="times(item.createdAt)" align="center"></uv-text>
								<view :class="item.role=='user'?'middle_item user':'middle_item'">
									<!-- <view class="fill">
										<el-image fit="fill"
											:src="item.role=='user'?(vuex_user.baseUrl+vuex_user.portrait):'/static/ai.svg'"></el-image>
									</view> -->
									<view
										:style="'background-color:'+dialogueColor+';border-radius: 10px;padding:5px  10px 0px 10px;margin:0px 0px;'">
										<view v-if="item.content">
											<contents :style="'height: auto;background-color:'+dialogueColor"
												:type="tabbarsValue" :item="item" :index="index"
												@del-event="resDelChat">
											</contents>
										</view>
										<view v-else>
											<uv-loading-icon color="red"></uv-loading-icon>
										</view>
									</view>
									<view style="opacity: 0;width: 45px;height: 40px;">00000</view>
								</view>
							</view>
						</view>
						<el-link style="font-size: 12px;opacity: 0;height: 0px !important;"
							type="primary">{{fill}}</el-link>
					</view>
					<!-- {{articles()}} -->
				</el-main>
				<view
					style="background-color: aquamarine;display: flex;justify-content: space-between;align-items: center;border: 1px solid #eeeeee;height: auto;padding: 5px;border-radius: 5px;margin: 0px 5px;">
					<el-tooltip effect="dark" content="请注意图片是否有插入！" placement="top">
						<uv-button size="mini" text="插入图片" @click="msg=msg+articles()"></uv-button>
					</el-tooltip>

					<view v-for="(btn, y) in exampleButtons" :key="y">
						<el-tooltip effect="dark" :content="btn.tip" placement="top">
							<uv-button size="mini" @click="msg=btn.content" :text="btn.text"></uv-button>
						</el-tooltip>
					</view>
				</view>
				<el-footer
					style="border-radius: 15px;background-color: #eee;padding:10px 5px 5px;margin:10px 5px;height: auto;bottom: 0px;">
					<view v-if="uploads" class="pos_image"
						:style="imageUrl[0]?'height: auto;':'height: 0px;opacity: 0;'">
						<view v-for="(item,idx) in imageUrl" :key="idx"
							style="position: relative;margin-right: 10px;margin-bottom: 5px;">
							<view class="item_dsh" @click="imageUrl.splice(idx, 1)">
								<uv-icon color="#FFF" bold name="close"></uv-icon>
							</view>
							<uv-image @click="preview(item.url)" mode="fill" :src="item.url" width="60px" height="60px"
								radius="6px"></uv-image>
						</view>
					</view>
					<view v-if="imageUrl[0]&& uploads" style="margin-top: 6px;margin-bottom: 2px;">
						<uv-line color="#2979ff"></uv-line>
					</view>

					<el-input :disabled="song" @focus="$uv.os() != 'windows'?(state = false,parmShow= false):''"
						type="textarea" placeholder="请输入内容" :autosize="{ minRows: 2, maxRows: 5}" v-model="msg"
						show-word-limit>
					</el-input>
					<view style="margin-top: 5px;display: flex;justify-content: space-between;">
						<view class="uploads" @click="prefixclick">
							<uv-icon :style="uploads?'':'opacity: 0.2;'" name="camera-fill" size="30"></uv-icon>
						</view>
						<document maxCount="50" accept="jpg,jpeg,webp,png" ref="document" v-model="imageUrl">
						</document>
						<uv-button :disabled="song" style="height: 30px;width: 30px;" type="primary" shape="circle"
							@click="taskd"><i class="el-icon-top"></i></uv-button>
					</view>
				</el-footer>
			</el-container>
		</el-container>
		<uv-toast ref="toast"></uv-toast>
		<tabbars></tabbars>
	</view>
</template>

<script>
	// 引入
	import contents from '@/components/content/content';
	import history from '@/components/history/history';
	import tabbars from '@/components/tabbar/tabbar';
	import document from '@/components/document/document.vue';
	import {
		index,
		task,
		api,
		apiId,
		scroll,
		scrollName,
		delScroll
	} from '@/common/api.js';
	import headers from '@/components/header/header.vue';
	import asided from '@/pages/aside/aside.vue';
	import gpts from '@/pages/chat/aside/aside.vue';
	import config from '@/common/config'
	import {
		fetchEventSource
	} from '@microsoft/fetch-event-source';
	export default {
		components: {
			// 注册组件
			tabbars,
			contents,
			history,
			headers,
			asided,
			gpts,
			document
		},
		model: {
			prop: 'value', // 对应 props 的属性名
			event: 'input' // 触发事件名
		},
		props: {
			value: [String, Array],
			chatInfo: Object,
		},
		computed: {},
		watch: {
			// 监听data数据的变化
			chatInfo: {
				handler: function(newVal, oldVal) {
					if (newVal && newVal.task && newVal.task.chat) {
						this.list = newVal.task.chat
					} else {
						this.list = []
					}
				},
				deep: true
			},
		},
		data() {
			return {
				fill: config.fill,
				dialogueColor: '#F4F5F9',
				deepColor: '#4D4D4D',
				shallowColor: '#808080',
				lightColor: '#ccc',
				state: true,
				asideW: 70,
				asiW: 420,
				x: 30, // 初始边框宽度
				activeIndex: 0,
				startX: 0, // 触摸开始的X坐标
				endX: 0, // 触摸结束的X坐标
				tabbarsValue: 'fusion',
				msg: '',
				content: '',
				tips: '',
				seconds: 10,
				aicurrent: null,
				eventSourceStatus: true,
				song: false,
				aiType: 'OpenAI',
				chat: {},
				uploads: false,
				exampleButtons: [{
						text: '仿写示例',
						tip: '请注意这是个示例！',
						content: '根据上或下面的内容的风格样式仿写，只返回仿写内容(500个字内)\t\r'
					},
					{
						text: '续写示例',
						tip: '请注意这是个示例！',
						content: '根据上或下面的内容或图片续写，只返回续写内容(500个字内)\t\r'
					},
					{
						text: '标签示例',
						tip: '请注意这是个示例！',
						content: `根据上或下面的内容或图片用标签细分全概括出来，标签有：主体对象标签，场景描述标签，细节特征标签,人物服饰穿戴描述标签，人物身材描述标签，人物年龄性别描述标签；场景物体描述标签；艺术风格标签，媒介类型标签，色彩氛围标签；情绪表达标签，抽象概念标签；拍摄/制作参数标签，镜头焦距标签，构图类型标签；用途分类标签等；图片参数标签，图片分辨率标签，画幅比例标签等；每种标签应不少于4个标签词，最后删除所有标签分类，空标签词，只返回有标签词组成的不能重复字符串（用#分隔）\t\r`
					},
					{
						text: '标题示例',
						tip: '请注意这是个示例！',
						content: '根据上或下面的内容或图片写出概括标题，只返回标题(最大35个字内)\t\r'
					}
				],
				lists: [{
						"name": "GPT",
						"api": "/ttapi",
						"value": "OpenAI",
						"icon": "works",
						"tag": [
							"chat",
							"reasoning"
						],
						"discount": 0.8,
						"model": [{
								"tag": [
									"chat",
									"imageAnalysis"
								],
								"text": "gpt-4o-mini",
								"value": "gpt-4o-mini",
								"input": 0.15,
								"output": 0.6
							},
							{
								"tag": [
									"chat",
									"imageAnalysis"
								],
								"text": "gpt-4o",
								"value": "gpt-4o",
								"input": 5,
								"output": 15
							},
							{
								"tag": [
									"chat"
								],
								"text": "gpt-4.1-nano",
								"value": "gpt-4.1-nano",
								"input": 0.15,
								"output": 0.6
							},
							{
								"tag": [
									"chat",
									"reasoning"
								],
								"text": "gpt-4",
								"value": "gpt-4",
								"input": 30,
								"output": 60
							},
							{
								"tag": [
									"chat",
									"reasoning"
								],
								"text": "gpt-4-turbo",
								"value": "gpt-4-turbo",
								"input": 10,
								"output": 30
							},
							{
								"tag": [
									"chat",
									"reasoning"
								],
								"text": "gpt-3.5-turbo",
								"value": "gpt-3.5-turbo",
								"input": 3,
								"output": 6
							},
							{
								"tag": [
									"chat"
								],
								"text": "o1-preview",
								"value": "o1-preview",
								"input": 15,
								"output": 60
							},
							{
								"tag": [
									"chat"
								],
								"text": "o1-mini",
								"value": "o1-mini",
								"input": 3,
								"output": 12
							}
						]
					},
					{
						"name": "DpSk",
						"api": "/hyapi",
						"value": "huiyan",
						"icon": "works",
						"tag": [
							"chat"
						],
						"discount": 10,
						"model": [{
								"tag": [
									"chat",
									"reasoning"
								],
								"text": "deepseek-chat",
								"value": "deepseek-chat",
								"grouping": 1,
								"model": 0.07,
								"completion": 4
							},
							{
								"tag": [
									"chat",
									"reasoning"
								],
								"text": "deepseek-r1",
								"value": "deepseek-r1",
								"grouping": 1,
								"model": 0.28,
								"completion": 4
							}
						]
					}
				],

				devel: process.env.NODE_ENV === 'development',
				parmShow: false,
				list: null, // 聊天内容
				quota: 0,
				imageUrl: [
					// 	{
					// 	"type": "image",
					// 	"url": "http://cdn.readend.com/66d593e2d900bdf6998aa1e1/4F12E8B9D5080C29C83B0CE9000A1ABF_1757063991338_6kqzh0.jpg?x-oss-process=image/resize,w_400,m_lfit",
					// 	"size": 184463,
					// 	"name": "4F12E8B9D5080C29C83B0CE9000A1ABF.jpg",
					// 	// "status": "success",
					// 	"message": "",
					// 	// "path": "/temp/image_1757057867160.jpg"
					// },
				],
			}
		},
		mounted() {
			this.tabbarsValue = this.pages();
			// var model = this.aiList;
			if (JSON.stringify(this.chatInfo) != '{}') {
				var model = this.lists;
				let chat;
				chat = this.chatInfo?.task?.taskInfo;
				for (var i = 0; i < model.length; i++) {
					if (chat && chat.ai && model[i].value == chat.ai &&
						chat.tag) {
						this.chat = {
							ai: chat.ai,
							text: chat.text,
							model: chat.model,
							tag: chat.tag,
							series: chat.series,
							messages: chat.messages,
							n: chat.n,
							temperature: chat.temperature,
							top_p: chat.top_p,
							presence_penalty: chat.presence_penalty,
							frequency_penalty: chat.frequency_penalty,
						};
					}
				}
			} else {
				this.aicurrent = 0;
			}
		},
		methods: {
			preview(e) { // 预览图片
				uni.previewImage({
					// current: i,
					urls: [e]
				});
			},
			uv_video(e) {
				let src = [];
				if (e?.content && e?.content[0]) {
					e = e.content[0];
				}
				if (e?.data && e?.data[0]) {
					src = [{
						url: e.data[0].url,
						type: 'video',
					}];
				}
				if (e?.videoUrl) {
					src.push({
						url: e.videoUrl,
						type: 'video',
						poster: e.imageUrl
					});
				}
				if (e?.musics) {
					for (var i = 0; i < e.musics.length; i++) {
						src.push({
							url: e.musics[i].videoUrl || e.musics[i].audioUrl,
							type: 'video',
							poster: e.musics[i].imageUrl
						});
					}
				}
				return src;
			},
			uv_image(e) {
				let src = [];
				if (e?.content && e?.content[0]) {
					e = e.content[0];
				}
				if (e?.data && e?.data[0]) {
					src = [{
						url: e.data[0].url,
					}];
				}
				if (e?.imageUrl) {
					src = [{
						url: e.imageUrl,
					}];
				}
				if (e?.videoFirstFrame) {
					src = [{
						url: e.videoFirstFrame,
					}];
				}
				if (e?.targetImage) {
					src = [{
						url: e.targetImage,
					}];
				}
				if (e?.images) {
					for (var i = 0; i < e.images.length; i++) {
						src.push({
							url: e.images[i]
						});
					}
				}
				if (e?.url) {
					src = [{
						url: e.url,
					}];
				}
				if (e?.musics) {
					for (var i = 0; i < e.musics.length; i++) {
						src.push({
							url: e.musics[i].imageUrl
						});
					}
				}
				return src;
			},
			articles() {
				let article = '下面为正文内容：\n\r';
				let chatInfo = this.chatInfo;
				if (chatInfo) {
					if (chatInfo.name) {
						article += '标题：' + chatInfo.name + '\n\r';
					}
					if (chatInfo.des) {
						article += '描述：' + chatInfo.des + '\n\r';
					}
					if (chatInfo.tags) {
						article += '标签：' + chatInfo.tags + '\n\r';
					}

					if (chatInfo.task == "fusion") {
						if (chatInfo.content[0]) {
							article += '内容：' + chatInfo.content[0] + '\n\r';
						}
					} else {
						if (chatInfo.content[0]) {
							this.imageUrl = this.uv_video(chatInfo)[0] ? this.uv_video(chatInfo) : this.uv_image(chatInfo)
							// article += '其他参数：' + JSON.stringify(this.chatInfo.content[0])+ ';';
						}

					}
					if (chatInfo.cover) {
						this.imageUrl.push({
							url: chatInfo.cover
						});
					}

					console.log(chatInfo, JSON.stringify(this.imageUrl));
				}
				return '';
			},
			tabsclicke(e, a) {
				this.aicurrent = e.index;
			},
			reschat(e) {
				this.chat = e;
				if (this.chat['tag'] && this.chat['tag'].includes('imageAnalysis')) {
					this.uploads = true;
				} else {
					this.uploads = false;
				}
			},
			prefixclick() {
				if (this.uploads) {
					this.$nextTick(() => {
						// this.$refs.uploads.handleClick();
						this.$refs.document.visible();
					});
				}
			},
			delex(i) {
				this.list = [];
				this.$emit('save', []); // 触发事件更新父组件变量
			},
			async taskd() {
				var that = this;
				if (!this.msg) {
					this.$refs.toast.show({
						type: 'error',
						message: "要提问的内容为空！"
					})
				}
				this.$refs.toast.show({
					message: "发送中。。。",
					duration: '2000'
				});
				this.song = true;
				var con = JSON.parse(JSON.stringify(this.chat), true);
				let dfds = null;
				if (this.imageUrl[0] && this.uploads) {
					dfds = {
						role: 'user',
						content: [{
							"type": "text",
							"text": this.msg
						}],
					}
					for (var i = 0; i < this.imageUrl.length; i++) {
						dfds.content.push({
							"type": "image_url",
							"image_url": {
								"url": this.imageUrl[i].url
								// "url": 'https://api.readend.com/dpc/temp/mini_image_1736933435723.png'
							}
						});
					}
				} else {
					dfds = {
						role: 'user',
						content: this.msg,
					}
				}
				if (con['messages']) {
					con['messages'] = [...con.messages, dfds];
				} else {
					con['messages'] = [dfds];
				}
				// 定义一个url，'/v1/chat/completions' '/stream/chat'
				const url = "/dpc" + this.aiApi + (this.devel ? '/v1/chat/completions' :
					'/v1/chat/completions')
				const ctrlAbout = new AbortController();
				fetchEventSource(url, {
					method: 'POST',
					headers: {
						'Content-Type': 'application/json',
						'Authorization': "Bearer " + this.aes_decrypt(this.vuex_token),
						'Connection': 'keep-alive',
					},
					body: JSON.stringify({
						"ai": con['ai'],
						"model": con['model'],
						"series": con['series'],
						"messages": JSON.stringify(con['messages']),
						"type": 'fusion',
						"api": 'article',
						"chat_id": this.value ? this.value : null,
					}),
					signal: ctrlAbout.signal,
					openWhenHidden: true, // 在浏览器标签页隐藏时保持与服务器的EventSource连接
					async onopen(response) {
						//建立连接的回调
						dfds['type'] = "text";
						dfds['createdAt'] = new Date();
						if (!that.list) {
							that.list = [];
						}
						that.list.push(dfds);
						that.msg = null;
						that.imageUrl = [];
						that.list.push({
							type: 'text',
							role: 'assistant',
							content: '',
							quota: 0
						});
					},
					onmessage(e) {
						// console.log('onmessage', e);
						try {
							if (e.data === '[DONE]') {
								that.song = false;
								ctrlAbout.abort();
								return;
							}
							if (!that.eventSourceStatus) {
								// 手动终止
								that.song = false;
								ctrlAbout.abort();
								return;
							}
							const res = e.data && JSON.parse(e.data);
							// console.log("流式数据", res);
							if (res?.code == 201 || res?.code == 401) {
								that.list[that.list.length - 1].content = res?.msg;
								that.$refs.toast.show({
									type: 'error',
									message: res?.msg || "发送失败！",
									duration: '2000'
								});
								that.song = false;
								ctrlAbout.abort();
								return;
							}
							if (res?.quota) {
								const quota = res?.quota ? res.quota : 0;
								that.list[that.list.length - 1].quota = quota;
							} else {
								const {
									content = ''
								} = (res?.choices && res?.choices[0]?.delta) ? res?.choices[0]?.delta: '';
								that.list[that.list.length - 1].content += content;
							}
						} catch (err) {
							console.log(e.data, e.data.msg);
						}
					},
					onerror(err) {
						//连接出现异常回调
						that.song = false;
						console.log((new Date().getTime()), 'error', err)
						// 取消请求
						throw err
					},
					onclose(e) {
						console.log(e);
						that.song = false;
						that.eventSourceStatus = true;
						ctrlAbout.abort();
						return;
					}
				});
			},
			pages() {
				var pages = getCurrentPages() // 获取栈实例
				let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
				let currentPage = pages[pages.length - 1]['$page']['fullPath'] //当前页面路径(带参数)
				return currentPage.split('/')[2];
			},
			cTime(index) {
				if (index === 0) return true;
				if (!this.list[index - 1]?.createdAt || !this.list[index]?.createdAt) return false;

				const prevTime = new Date(this.list[index - 1].createdAt).getTime();
				const currTime = new Date(this.list[index].createdAt).getTime();
				return Math.abs(currTime - prevTime) > 20 * 60 * 1000; // 20分钟
			},
			times(time) {
				return " -- " + uni.$uv.timeFrom(new Date(time).getTime()) + " -- ";
			},
			routes(url) {
				this.routed('/pages' + url);
			},
			routed(url) {
				console.log('routed', url)
				uni.$uv.route({
					url: url,
					intercept(params, next) {
						// console.log(params, next)
						uni.showLoading({
							title: '等待中...'
						})
						// 模拟处理等待
						setTimeout(() => {
							uni.hideLoading();
							next(true);
						}, 1000)
					}
				})
			}
		}
	}
</script>

<style scoped lang="scss">
	.fusion-chat {
		// height: 100vh;
		border: 1px solid #ddd;
		border-radius: 10px;
		margin: 1px 10px;

		.gpts2 {
			max-width: 450px;
			margin: 5px;
			padding: 0px 6px;
			borber: 1px solid #f2f2f2;
			border-radius: 10px;
			background-color: rgba(200, 200, 200, 0.3);
		}

		.gptstrue {}

		.gptsfalse {
			width: 0px;
			height: 0px;
			overflow: hidden;
		}

		.middle_item {
			margin-bottom: 5px;
			display: flex;
			align-items: flex-start;
			// width: 100%;
			flex-direction: row;
			flex-wrap: nowrap;
			align-content: stretch;
			justify-content: flex-start;

			.selectable-text {
				-webkit-user-select: text;
				/* Safari */
				-moz-user-select: text;
				/* Firefox */
				-ms-user-select: text;
				/* IE 10+ */
				user-select: text;
				/* Standard syntax */
			}

			::v-deep .code-block {
				background-color: #f8f8f8;
				border: 1px solid #ddd;
				padding: 5px 10px;
				border-radius: 5px;
				white-space: pre-wrap;
				word-break: break-all;
				font-family: 'Courier New', Courier, monospace;
				font-size: 14px;
			}



			.fill {
				width: 40px;
				height: 40px;
				margin: 0px;
				padding: 2px;
				border-radius: 20px;

				::v-deep .el-image__inner {
					width: 40px;
					height: 40px;
					border-radius: 20px;
				}
			}

		}

		.user {
			flex-direction: row-reverse;
		}

		.pos_image {
			display: flex;
			justify-content: flex-start;
			flex-wrap: wrap;
			align-items: center;
			background-color: #fff;
			border-radius: 10px;
			padding: 5px 0px 0px 5px;

			.item_dsh {
				position: absolute;
				z-index: 10;
				top: 0px;
				right: 0px;
				background-color: #000;
				padding: 5px 6px;
				color: #fff;
				border-top-right-radius: 10px;
				border-bottom-left-radius: 10px;
				cursor: pointer;
			}
		}

		.uploads {
			cursor: pointer;
		}
		.uploads:hover {
			background-color: #f6f6f6;
			border-radius: 10px;
		}
		



		.el-textarea {
			width: 100%;

			::v-deep .el-textarea__inner {
				border: 0px;
				color: #000;
				padding: 0px;
				width: 100%;
				background-color: rgba(0, 0, 0, 0) !important;
			}
		}

		.pos_image {
			::v-deep .uv-upload__button {
				display: none;
			}
		}

	}
</style>